package br.edu.ufcg.embedded.util.algo;

import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

import org.jgrapht.Graph;
import org.jgrapht.graph.DefaultEdge;

import br.edu.ufcg.embedded.domain.CustomVertex;
import br.edu.ufcg.embedded.domain.DirectedGraphBuilder;
import br.embedded.socialapp.data.FriendshipDAO;

public class GraphGenerator {
	
	private DirectedGraphBuilder graphBuilder;
	
	public GraphGenerator() {
		
		this.graphBuilder = new DirectedGraphBuilder();
	}
	
	public Graph<String, DefaultEdge> generate(int sampleSize, Hashtable<String, Float> matrix) {

		Hashtable<String, Integer> counters = new Hashtable<String, Integer>(matrix.size());
		
		String inicial = null;

		for (String key : matrix.keySet()) {

			counters.put(key, calculatePopulation(sampleSize, matrix.get(key)));
		}
		
		inicial = counters.toString();

		Queue<CustomVertex> queue = new LinkedList<CustomVertex>();
		CustomVertex root = FriendshipDAO.getInstance().getRandomVertices("H", 1).get(0);
		
		List<CustomVertex> list = FriendshipDAO.getInstance().getFollowers(root);

		for (CustomVertex customVertex : list) {
			queue.add(customVertex);
		}
		
		list = null;
		
		graphBuilder.add(root.toString());
		counters.put(root.getClassification(), counters.get(root.getClassification()) -1);

		while (!queue.isEmpty()) {

			CustomVertex vertex = queue.remove();
			
			graphBuilder.add(vertex.getParent());
			graphBuilder.add(vertex.toString());
			boolean edgeAdded = graphBuilder.addEdge(vertex.getParent(), vertex.toString());
			
			if (edgeAdded) { 

				int tmpCount = counters.get(vertex.getClassification());

				if (tmpCount > 0)
				{
					//graphBuilder.add(vertex.getParent(), vertex.toString());
					counters.put(vertex.getClassification(), tmpCount -1);

					if (!checkCounters(counters)) {

						List<CustomVertex> n2 = FriendshipDAO.getInstance().getFollowers(vertex);

						for (CustomVertex v : n2) {

							//if (!graphBuilder.hasVertex(v.toString()) && counters.get(v.getClassification()) > 0)
							if (counters.get(v.getClassification()) > 0)
								queue.add(v);
						}
					}
					else
						break;
				}

				//System.out.println(counters);
			}
		}
		
		list = FriendshipDAO.getInstance().getRandomVertices("A", counters.get("A"));
		int count = counters.get("A"); 
			
		for (CustomVertex v : list) 
		{
			if (graphBuilder.add(v.toString()))
				count--;
		}
		counters.put("A", count);
		
		System.out.println("Inicial >>> " + inicial);
		System.out.println("Final >>> " + counters);
		
		return graphBuilder.getGraph();
	}
	
	private int calculatePopulation(int sampleSize, float rate) {
		
		return Math.round((sampleSize * rate));
	}
	
	private boolean checkCounters(Hashtable<String, Integer> counters) {
		
		for (int value : counters.values()) {
			
			if (value > 0)
				return false;
		}
		
		return true;
	}	
}